package ru.mirent.console.colors;

/**
 * Форматированный вывод текста в консоль IDE. Примеры форматированного вывода и применения класса содержатся в тестах.
 */
public class FormatterTextColor {
    /**
     * Управляющая последовательность символов, указывающая на блок форматирования текста.
     */
    private static final String OPEN_START_FORMAT = "\033[";

    /**
     * Символ для завершения формирования блока форматирования текста.
     */
    private static final String M = "m";

    /**
     * Очищенный блок форматирования текста
     */
    private static final String CLEAR_START_FORMAT = "";

    /**
     * Строка с символом начала блока форматирования текста.
     */
    private String startFormat = CLEAR_START_FORMAT;

    /**
     * Результирующий текст.
     */
    private final StringBuilder resultText = new StringBuilder();

    /**
     * Цвет фона текста.
     */
    private ColorValue backgroundColor = BgColor.create(BC.DEFAULT);

    /**
     * Цвет букв текста.
     */
    private TC textColor = TC.DEFAULT;

    /**
     * Флаг, указывающий на необходимость завершения строки.
     */
    private boolean isSetDefaultFormat = true;

    /**
     * Добавить текст с текущими настройками форматирования.
     * @param text добавляемый текст
     * @return {@link FormatterTextColor} текущий объект
     */
    public FormatterTextColor append(String text) {
        if (startFormat.equals(OPEN_START_FORMAT)) {
            resultText.append(M);
        }
        resultText.append(text);
        startFormat = CLEAR_START_FORMAT;
        return this;
    }

    /**
     * Указать цвет букв текста.
     * @param textColor цвет {@link TC}
     * @return {@link FormatterTextColor} текущий объект
     */
    public FormatterTextColor startTextColor(TC textColor) {
        this.textColor = textColor;
        if (startFormat.isEmpty()) {
            startFormat = OPEN_START_FORMAT;
            resultText.append(startFormat).append(textColor.getValue());
        } else {
            resultText.append(";").append(textColor.getValue());
        }

        return this;
    }

    /**
     * Установить цвет букв текста в значение по умолчанию.
     * @return {@link FormatterTextColor} текущий объект
     */
    public FormatterTextColor stopTextColor() {
        return startTextColor(TC.DEFAULT);
    }

    /**
     * Указать цвет фона текста.
     * @param backgroundColor цвет фона {@link BC}
     * @return {@link FormatterTextColor} текущий объект
     */
    public FormatterTextColor startBackgroundColor(BgColor backgroundColor) {
        this.backgroundColor = backgroundColor;
        if (startFormat.isEmpty()) {
            startFormat = OPEN_START_FORMAT;
            resultText.append(OPEN_START_FORMAT).append(backgroundColor.getValue());
        } else {
            resultText.append(";").append(backgroundColor.getValue());
        }

        return this;
    }

    /**
     * Установить цвет фона текста в значение по умолчанию.
     * @return {@link FormatterTextColor} текущий объект
     */
    public FormatterTextColor stopBackgroundColor() {
        return startBackgroundColor(BgColor.create(BC.DEFAULT));
    }

    /**
     * Очистить форматирование.
     * @return {@link FormatterTextColor} текущий объект
     */
    public FormatterTextColor defaultFormat() {
        if (isSetDefaultFormat) {
            backgroundColor = BgColor.create(BC.DEFAULT);
            textColor = TC.DEFAULT;
            resultText.append(OPEN_START_FORMAT).append(Symbols.RESET_TO_DEFAULT.getValue()).append(M);
            startFormat = CLEAR_START_FORMAT;
            isSetDefaultFormat = false;
        }

        return this;
    }

    /**
     * Очистить форматирование для дальнейшего вывода и вернуть форматированный текст.
     * @return форматированный текст {@link String}
     */
    public String build() {
        if (isSetDefaultFormat) {
            defaultFormat();
        }
        return resultText.toString();
    }
}
